<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>Optimistic Concurrency Control | Elasticsearch: The Definitive Guide [2.x] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch: The Definitive Guide [2.x]">
<link rel="up" href="data-in-data-out.html" title="Data In, Data Out">
<link rel="prev" href="version-control.html" title="Dealing with Conflicts">
<link rel="next" href="partial-updates.html" title="Partial Updates to Documents">
<meta name="DC.type" content="Learn/Docs/Legacy/Elasticsearch/Definitive Guide/2.x">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="2.x">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<p>
  <strong>WARNING</strong>: The 2.x versions of Elasticsearch have passed their
  <a href="https://www.elastic.co/support/eol">EOL dates</a>. If you are running
  a 2.x version, we strongly advise you to upgrade.
</p>
<p>
  This documentation is no longer maintained and may be removed. For the latest
  information, see the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html">current
  Elasticsearch documentation</a>.
</p>
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: The Definitive Guide [2.x]</a></span>
»
<span class="breadcrumb-link"><a href="getting-started.html">Getting Started</a></span>
»
<span class="breadcrumb-link"><a href="data-in-data-out.html">Data In, Data Out</a></span>
»
<span class="breadcrumb-node">Optimistic Concurrency Control</span>
</div>
<div class="navheader">
<span class="prev">
<a href="version-control.html">« Dealing with Conflicts</a>
</span>
<span class="next">
<a href="partial-updates.html">Partial Updates to Documents »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="optimistic-concurrency-control"></a>Optimistic Concurrency Control<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/030_Data/40_Version_control.asciidoc">edit</a>
</h2>
</div></div></div>
<p>Elasticsearch is distributed.  When documents are created, updated, or deleted,
the new version of the document has to be replicated to other nodes in the
cluster.  Elasticsearch is also asynchronous and  concurrent, meaning that
these replication requests are sent in parallel, and may arrive at their
destination <em>out of sequence</em>. Elasticsearch needs a way of ensuring that an older
version of a document never overwrites a newer version.</p>
<p>When we discussed <code class="literal">index</code>, <code class="literal">get</code>, and <code class="literal">delete</code> requests previously, we pointed out
that every document has a <code class="literal">_version</code> number that is incremented whenever a
document is changed. Elasticsearch uses this <code class="literal">_version</code> number to ensure that
changes are applied in the correct order. If an older version of a document
arrives after a new version, it can simply be ignored.</p>
<p>We can take advantage of the <code class="literal">_version</code> number to ensure that conflicting
changes made by our application do not result in data loss. We do this by
specifying the <code class="literal">version</code> number of the document that we wish to change.  If that
version is no longer current, our request fails.</p>
<p>Let’s create a new blog post:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">PUT /website/blog/1/_create
{
  "title": "My first blog entry",
  "text":  "Just trying this out..."
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_Concurrency.json"></div>
<p>The response body tells us that this newly created document has <code class="literal">_version</code>
number <code class="literal">1</code>.  Now imagine that we want to edit the document: we load its data
into a web form, make our changes, and then save the new version.</p>
<p>First we retrieve the document:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /website/blog/1</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_Concurrency.json"></div>
<p>The response body includes the same <code class="literal">_version</code> number of <code class="literal">1</code>:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "_index" :   "website",
  "_type" :    "blog",
  "_id" :      "1",
  "_version" : 1,
  "found" :    true,
  "_source" :  {
      "title": "My first blog entry",
      "text":  "Just trying this out..."
  }
}</pre>
</div>
<p>Now, when we try to save our changes by reindexing the document, we specify
the <code class="literal">version</code> to which our changes should be applied:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">PUT /website/blog/1?version=1 <a id="CO11-1"></a><i class="conum" data-value="1"></i>
{
  "title": "My first blog entry",
  "text":  "Starting to get the hang of this..."
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_Concurrency.json"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO11-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>We want this update to succeed only if the current <code class="literal">_version</code> of this
document in our index is version <code class="literal">1</code>.</p>
</td>
</tr>
</table>
</div>
<p>This request succeeds, and the response body tells us that the <code class="literal">_version</code>
has been incremented to <code class="literal">2</code>:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">{
  "_index":   "website",
  "_type":    "blog",
  "_id":      "1",
  "_version": 2
  "created":  false
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_Concurrency.json"></div>
<p>However, if we were to rerun the same index request, still specifying
<code class="literal">version=1</code>, Elasticsearch would respond with a <code class="literal">409 Conflict</code> HTTP response
code, and a body like the following:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">{
   "error": {
      "root_cause": [
         {
            "type": "version_conflict_engine_exception",
            "reason": "[blog][1]: version conflict, current [2], provided [1]",
            "index": "website",
            "shard": "3"
         }
      ],
      "type": "version_conflict_engine_exception",
      "reason": "[blog][1]: version conflict, current [2], provided [1]",
      "index": "website",
      "shard": "3"
   },
   "status": 409
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_Concurrency.json"></div>
<p>This tells us that the current <code class="literal">_version</code> number of the document in
Elasticsearch is <code class="literal">2</code>, but that we specified that we were updating version <code class="literal">1</code>.</p>
<p>What we do now depends on our application requirements.  We could tell the
user that somebody else has already made changes to the document, and to review the changes before trying to save them again.
Alternatively, as in the case of the widget <code class="literal">stock_count</code> previously, we could
retrieve the latest document and try to reapply the change.</p>
<p>All APIs that update or delete a document accept a <code class="literal">version</code> parameter, which
allows you to apply optimistic concurrency control to just the parts of your
code where it makes sense.</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_using_versions_from_an_external_system"></a>Using Versions from an External System<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch-definitive-guide/edit/2.x/030_Data/40_Version_control.asciidoc">edit</a>
</h3>
</div></div></div>
<p>A common setup is to use some other database as the primary data store and
Elasticsearch to make the data searchable, which means that all changes to the
primary database need to be copied across to Elasticsearch as they happen.  If
multiple processes are responsible for this data synchronization, you may
run into concurrency problems similar to those described previously.</p>
<p>If your main database already has version numbers—​or a value such as
<code class="literal">timestamp</code> that can be used as a version number—​then  you can reuse these
same version numbers in Elasticsearch by adding <code class="literal">version_type=external</code> to the
query string. Version numbers must be integers greater than zero and less than
about <code class="literal">9.2e+18</code>--a positive <code class="literal">long</code> value in Java.</p>
<p>The way external version numbers are handled is a bit different from the
internal version numbers  we discussed previously.  Instead of checking that the
current <code class="literal">_version</code> is <em>the same</em> as the one specified in the request,
Elasticsearch checks that the current <code class="literal">_version</code> is <em>less than</em> the specified
version. If the request succeeds, the external version number is stored as the
document’s new <code class="literal">_version</code>.</p>
<p>External version numbers can be specified not only on
index and delete requests, but also when <em>creating</em> new documents.</p>
<p>For instance, to create a new blog post with an external version number
of <code class="literal">5</code>, we can do the following:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">PUT /website/blog/2?version=5&amp;version_type=external
{
  "title": "My first external blog entry",
  "text":  "Starting to get the hang of this..."
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_External_versions.json"></div>
<p>In the response, we can see that the current <code class="literal">_version</code> number is <code class="literal">5</code>:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "_index":   "website",
  "_type":    "blog",
  "_id":      "2",
  "_version": 5,
  "created":  true
}</pre>
</div>
<p>Now we update this document, specifying a new <code class="literal">version</code> number of <code class="literal">10</code>:</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">PUT /website/blog/2?version=10&amp;version_type=external
{
  "title": "My first external blog entry",
  "text":  "This is a piece of cake..."
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/030_Data/40_External_versions.json"></div>
<p>The request succeeds and sets the current <code class="literal">_version</code> to <code class="literal">10</code>:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "_index":   "website",
  "_type":    "blog",
  "_id":      "2",
  "_version": 10,
  "created":  false
}</pre>
</div>
<p>If you were to rerun this request, it would fail with the same conflict error
we saw before, because the specified external version number is not higher
than the current version in Elasticsearch.</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="version-control.html">« Dealing with Conflicts</a>
</span>
<span class="next">
<a href="partial-updates.html">Partial Updates to Documents »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
